From c38a84195269fe27ac6e2e714b89c86bf8aab78d Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Fri, 18 Feb 2005 13:34:28 +0000 Subject: [PATCH] bitkeeper revision 1.1223 (4215eee4gqIO-1mu8V6FHhIhoaqaiQ) Change priv-op emulation behaviour to fail silently in some cases rather than propagate the fault (still non-silent in debug builds!). Also be careful in running user-specified RDMSR/WRMSR: an invalid MSR index causes a GP(0) fault. Signed-off-by: Keir Fraser --- xen/arch/x86/dom0_ops.c | 4 ++-- xen/arch/x86/traps.c | 23 +++++++++---------- xen/include/asm-x86/config.h | 12 ++++++---- xen/include/asm-x86/msr.h | 43 +++++++++++++++++++++++++----------- 4 files changed, 51 insertions(+), 31 deletions(-) diff --git a/xen/arch/x86/dom0_ops.c b/xen/arch/x86/dom0_ops.c index 0f455c6800..3c11c8af6d 100644 --- a/xen/arch/x86/dom0_ops.c +++ b/xen/arch/x86/dom0_ops.c @@ -36,13 +36,13 @@ static unsigned long msr_hi; static void write_msr_for(void *unused) { if (((1 << current->processor) & msr_cpu_mask)) - wrmsr(msr_addr, msr_lo, msr_hi); + (void)wrmsr_user(msr_addr, msr_lo, msr_hi); } static void read_msr_for(void *unused) { if (((1 << current->processor) & msr_cpu_mask)) - rdmsr(msr_addr, msr_lo, msr_hi); + (void)rdmsr_user(msr_addr, msr_lo, msr_hi); } long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 36280de46c..a2ac58ad0c 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -375,12 +375,11 @@ static int emulate_privileged_op(struct xen_regs *regs) break; case 0x09: /* WBINVD */ + /* Ignore the instruction if unprivileged. */ if ( !IS_CAPABLE_PHYSDEV(ed->domain) ) - { DPRINTK("Non-physdev domain attempted WBINVD.\n"); - goto fail; - } - wbinvd(); + else + wbinvd(); break; case 0x20: /* MOV CR?, */ @@ -441,21 +440,21 @@ static int emulate_privileged_op(struct xen_regs *regs) break; case 0x30: /* WRMSR */ + /* Ignore the instruction if unprivileged. */ if ( !IS_PRIV(ed->domain) ) - { - DPRINTK("Non-priv domain attempted WRMSR.\n"); + DPRINTK("Non-priv domain attempted WRMSR(%p,%08lx,%08lx).\n", + regs->ecx, (long)regs->eax, (long)regs->edx); + else if ( wrmsr_user(regs->ecx, regs->eax, regs->edx) ) goto fail; - } - wrmsr(regs->ecx, regs->eax, regs->edx); break; case 0x32: /* RDMSR */ if ( !IS_PRIV(ed->domain) ) - { - DPRINTK("Non-priv domain attempted RDMSR.\n"); + DPRINTK("Non-priv domain attempted RDMSR(%p,%08lx,%08lx).\n", + regs->ecx, (long)regs->eax, (long)regs->edx); + /* Everyone can read the MSR space. */ + if ( rdmsr_user(regs->ecx, regs->eax, regs->edx) ) goto fail; - } - rdmsr(regs->ecx, regs->eax, regs->edx); break; default: diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h index 787d953691..84a0492e1d 100644 --- a/xen/include/asm-x86/config.h +++ b/xen/include/asm-x86/config.h @@ -206,8 +206,10 @@ extern void __out_of_line_bug(int line) __attribute__((noreturn)); #define __GUEST_SS 0x082b /* For generic assembly code: use macros to define operation/operand sizes. */ -#define __OS "q" /* Operation Suffix */ -#define __OP "r" /* Operand Prefix */ +#define __OS "q" /* Operation Suffix */ +#define __OP "r" /* Operand Prefix */ +#define __FIXUP_ALIGN ".align 8" +#define __FIXUP_WORD ".quad" #elif defined(__i386__) @@ -264,8 +266,10 @@ extern void __out_of_line_bug(int line) __attribute__((noreturn)); #define __HYPERVISOR_DS 0x0810 /* For generic assembly code: use macros to define operation/operand sizes. */ -#define __OS "l" /* Operation Suffix */ -#define __OP "e" /* Operand Prefix */ +#define __OS "l" /* Operation Suffix */ +#define __OP "e" /* Operand Prefix */ +#define __FIXUP_ALIGN ".align 4" +#define __FIXUP_WORD ".long" #endif /* __i386__ */ diff --git a/xen/include/asm-x86/msr.h b/xen/include/asm-x86/msr.h index a7178f2e3b..dd01e9642a 100644 --- a/xen/include/asm-x86/msr.h +++ b/xen/include/asm-x86/msr.h @@ -1,29 +1,46 @@ #ifndef __ASM_MSR_H #define __ASM_MSR_H -/* - * Access to machine-specific registers (available on 586 and better only) - * Note: the rd* operations modify the parameters directly (without using - * pointer indirection), this allows gcc to optimize better - */ - #define rdmsr(msr,val1,val2) \ __asm__ __volatile__("rdmsr" \ : "=a" (val1), "=d" (val2) \ : "c" (msr)) -#define rdmsrl(msr,val) do { unsigned long a__,b__; \ - __asm__ __volatile__("rdmsr" \ - : "=a" (a__), "=d" (b__) \ - : "c" (msr)); \ - val = a__ | (b__<<32); \ -} while(0); - #define wrmsr(msr,val1,val2) \ __asm__ __volatile__("wrmsr" \ : /* no outputs */ \ : "c" (msr), "a" (val1), "d" (val2)) +#define rdmsr_user(msr,val1,val2) ({\ + int _rc = 0; \ + __asm__ __volatile__( \ + "1: rdmsr\n2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: movl $1,%2\n; jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " "__FIXUP_ALIGN"\n" \ + " "__FIXUP_WORD" 1b,3b\n" \ + ".previous\n" \ + : "=a" (val1), "=d" (val2), "=r" (_rc) \ + : "c" (msr)); \ + _rc; }) + +#define wrmsr_user(msr,val1,val2) ({\ + int _rc = 0; \ + __asm__ __volatile__( \ + "1: wrmsr\n2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: movl $1,%0\n; jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " "__FIXUP_ALIGN"\n" \ + " "__FIXUP_WORD" 1b,3b\n" \ + ".previous\n" \ + : "=r" (_rc) \ + : "c" (msr), "a" (val1), "d" (val2)); \ + _rc; }) + #define rdtsc(low,high) \ __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)) -- 2.30.2